package com.qiusuo0226.core.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;

import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.qiusuo0226.common.constant.NumConstant;
import com.qiusuo0226.common.util.ListTool;
import com.qiusuo0226.core.mapper.AdministrativeDivisionMapper;
import com.qiusuo0226.core.pojo.dto.AdminDivisionDTO;
import com.qiusuo0226.core.pojo.entity.AdministrativeDivisionDO;
import com.qiusuo0226.core.service.AdministrativeDivisionSerivce;
import com.qiusuo0226.core.service.OrganizationService;
import org.apache.commons.collections4.MapUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.*;

/**
 * 行政区划数据处理层
 * @author qiusuo
 * @date 2022-04-05
 */
@Service
@Transactional
public class AdministrativeDivisionSerivceImpl extends ServiceImpl<AdministrativeDivisionMapper, AdministrativeDivisionDO> implements AdministrativeDivisionSerivce {


    @Autowired
    private OrganizationService organizationService;


    @Override
    public boolean insertBatch(List<AdministrativeDivisionDO> params) {
        return baseMapper.insertBatch(params);
    }

    @Override
    public List<AdministrativeDivisionDO> list() {
        List<AdministrativeDivisionDO> AdministrativeDivisionDOs = baseMapper.selectList(null);
        return ListTool.isEmpty(AdministrativeDivisionDOs) ? new ArrayList<>() : AdministrativeDivisionDOs;
    }

    @Override
    public List<Map<String,Object>> getListTreeByPid(long pid) {
        List<Map<String,Object>> AdministrativeDivisionDOs = baseMapper.selectListByPid(pid);
        AdministrativeDivisionDOs.forEach((item) -> {
            if (MapUtils.getObject(item, "isLeaf") instanceof Boolean) {
                return;
            }
            item.put("isLeaf", MapUtils.getIntValue(item, "isLeaf", 0) == 0 ? false : true);
        });
        return ListTool.isEmpty(AdministrativeDivisionDOs) ? new ArrayList<>() : AdministrativeDivisionDOs;
    }

    @Override
    public Map<String, Object> getListByPid(long pid, Integer pageNo, Integer pageSize, String searchInfo) {
        Page<AdministrativeDivisionDO> page = new Page<AdministrativeDivisionDO>(pageNo, pageSize);

        QueryWrapper<AdministrativeDivisionDO> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("parent_id", pid);
        queryWrapper.eq("deleted", "0");
        queryWrapper.like(!StringUtils.isBlank(searchInfo),"name", searchInfo);
        queryWrapper.orderByAsc("sort");
        Page<AdministrativeDivisionDO> pageRes = baseMapper.selectPage(page, queryWrapper);
        List<AdministrativeDivisionDO> records = pageRes.getRecords();
        Map<String, Object> res = new HashMap<>(NumConstant.N16);
        res.put("list", records);
        res.put("total", pageRes.getTotal());
        res.put("pageSize", pageRes.getSize());
        res.put("pageNo", pageRes.getCurrent());
        return res;
    }

    @Override
    public AdministrativeDivisionDO getParentById(long id) {
        return baseMapper.getParentById(id);
    }

    public int remove(long iid, String type) throws Exception {
        // 完全删除
        if (NumConstant.S1.equals(type)) {

        } else {
            // 区划删除
            QueryWrapper wrapper =  new QueryWrapper();
            wrapper.eq("parent_id", iid);

        }
        AdministrativeDivisionDO entity = new AdministrativeDivisionDO();
        entity.setDeleted("1");
        entity.setIid(iid);
        UpdateWrapper update = null;
        try {
            update = createUpdate(entity);
        } catch (Exception e) {
            throw new Exception(e.getMessage());
        }

        return baseMapper.update(null,update);
    }

    @Override
    public int removeList(List<Long> ids, Integer type) {
        // 完全删除，删除该行政区划以及所有子行政区划和后辈行政区划，被删除的行政区划下的所有组织机构会归档到"未分配组织机构"
        if (NumConstant.N1 == type) {
            List<AdministrativeDivisionDO> list = baseMapper.selectByIds(ids);
            removePojoList(list);
        } else {
            // 区划删除只删除当前行政区划，该行政区划下的所有子区划全部自动升一级，该行政区划下的所有组织机构会归档到"未分配组织机构"
            ids.forEach((iid) -> {
                // 获取当前行政区划的完整信息
                AdministrativeDivisionDO AdministrativeDivisionDO = baseMapper.selectById(iid);
                if (null == AdministrativeDivisionDO) {
                    return;
                }
                // 当前行政区划的父级区划
                Long pid = AdministrativeDivisionDO.getParentId();
                // 取出当前区划的所有子区划，修改子区划的父id为当前行政区划的父id
                QueryWrapper wrapper = new QueryWrapper();
                wrapper.eq("parent_id", iid);
                wrapper.eq("deleted", "0");
                List<AdministrativeDivisionDO> list = baseMapper.selectList(wrapper);
                if (!ListTool.isEmpty(list)) {
                    baseMapper.batchUpdatePid(list, pid);
                }
                // 修改当前行政区划下的组织机构归档到未分配的组织机构
                organizationService.moveAllToUnknownByDid(iid);
                // 修改当前区划的删除状态位为1
                UpdateWrapper updateWrapper = new UpdateWrapper();
                updateWrapper.eq("iid", iid);
                updateWrapper.set("deleted", "1");
                baseMapper.update(null, updateWrapper);
            });

        }
        return ids.size();
    }

    /**
     * 删除行政区划对象集合，并把删除的行政区划下的单位都放到未归档区中
     * @param list
     */
    public void removePojoList(List<AdministrativeDivisionDO> list) {
        // 遍历所有行政区划对象
        list.forEach((item) -> {
            // 取出当前区划的所有子区划。子区划递归删除
            QueryWrapper wrapper = new QueryWrapper();
            wrapper.eq("parent_id", item.getIid());
            wrapper.eq("deleted", "0");
            List<AdministrativeDivisionDO> pojoLists = baseMapper.selectList(wrapper);
            if(!ListTool.isEmpty(pojoLists)) {
                removePojoList(pojoLists);
            }
            // 修改当前行政区划下的组织机构归档到未分配的组织机构
            organizationService.moveAllToUnknownByDid(item.getIid());
            // 修改当前区划的删除状态位为1
            UpdateWrapper updateWrapper = new UpdateWrapper();
            updateWrapper.eq("iid", item.getIid());
            updateWrapper.set("deleted", "1");
            baseMapper.update(null, updateWrapper);
        });
    }

    @Override
    public AdministrativeDivisionDO add(AdministrativeDivisionDO AdministrativeDivisionDO) throws Exception {
        if (checkCodeExist(AdministrativeDivisionDO.getCode())) {
            throw new Exception("行政编码已存在");
        }
        Date date = new Date();
        AdministrativeDivisionDO.setDeleted("0");
        AdministrativeDivisionDO.setVersion(0);
        AdministrativeDivisionDO.setGmtModify(date);
        AdministrativeDivisionDO.setGmtCreate(date);
        int insert = baseMapper.insert(AdministrativeDivisionDO);
        QueryWrapper queryWrapper = new QueryWrapper();
        queryWrapper.eq("name", AdministrativeDivisionDO.getName());
        queryWrapper.eq("code", AdministrativeDivisionDO.getCode());
        queryWrapper.eq("deleted", "0");
        return baseMapper.selectOne(queryWrapper);
    }

    @Override
    public int modify(AdministrativeDivisionDO entity) throws Exception {
        UpdateWrapper update = null;
        try {
            update = createUpdate(entity);
            int update1 = baseMapper.update(null, update);
            return update1;
        } catch (Exception e) {
            throw new Exception(e.getMessage());
        }

    }

    @Override
    public List<AdminDivisionDTO> getTree() {
        List<AdminDivisionDTO> adminDivisions = baseMapper.getTree();
        Map<String, AdminDivisionDTO> adminDivisionMap = new HashMap<String, AdminDivisionDTO>(NumConstant.N16);
        adminDivisions.forEach((item) -> {
            adminDivisionMap.put(item.getIid(), item);
        });
        List<AdminDivisionDTO> res = new ArrayList<>();
        adminDivisions.forEach((item) -> {
            if ("0".equals(item.getParentId())) {
                res.add(item);
            } else {
                AdminDivisionDTO AdminDivisionDTO = adminDivisionMap.get(item.getParentId());
                try {
                    AdminDivisionDTO.getChildrens().add(item);
                } catch (Exception e) {
                    System.out.println(item.toString());
                    e.printStackTrace();
                }

            }
        });
        return res;
    }



    /**
     * 校验编码是否存在
     * @param code
     * @return
     */
    private boolean checkCodeExist(String code) {
        QueryWrapper<AdministrativeDivisionDO> wrapper = new QueryWrapper<>();
        wrapper.eq("code", code);
        wrapper.eq("deleted", "0");
        List<AdministrativeDivisionDO> AdministrativeDivisionDOs = baseMapper.selectList(wrapper);
        return ListTool.isNotEmpty(AdministrativeDivisionDOs);
    }

    /**
     * 构建修改方法。
     * 入参为需要修改的实体类，需要修改的属性赋值，不需要修改的属性置为null。
     *
     * @param entity 需要修改的实体类
     * @return
     * @throws Exception
     */
    private UpdateWrapper createUpdate(AdministrativeDivisionDO entity) throws Exception {
        if (null == entity.getIid()) {
            throw new IllegalArgumentException("入参实例缺少唯一标识iid");
        }
        QueryWrapper<AdministrativeDivisionDO> queryWrapperwrapper = new QueryWrapper<>();
        queryWrapperwrapper.eq("iid", entity.getIid());
        queryWrapperwrapper.eq("deleted", "0");
        AdministrativeDivisionDO AdministrativeDivisionDO = baseMapper.selectOne(queryWrapperwrapper);
        if (AdministrativeDivisionDO == null) {
            throw new IllegalArgumentException("入参实例唯一标识iid的数据不存在");
        }
        UpdateWrapper<AdministrativeDivisionDO> updateWrapper = new UpdateWrapper<>();
        updateWrapper.eq("iid", AdministrativeDivisionDO.getIid())
                .eq("version", AdministrativeDivisionDO.getVersion())
                .set("version", AdministrativeDivisionDO.getVersion() + 1)
                .set("gmt_modify", new Date());

        if (null != entity.getCode()) {
            QueryWrapper<AdministrativeDivisionDO> wrapper = new QueryWrapper();
            wrapper.eq("code", entity.getCode()).eq("deleted", "0").ne("iid", entity.getIid());
            AdministrativeDivisionDO AdministrativeDivisionDOs = baseMapper.selectOne(wrapper);
            if (null != AdministrativeDivisionDOs) {
                throw new Exception("区划编码已存在");
            }
            updateWrapper.set("code", entity.getCode());
        }
        if (null != entity.getName()) {
            updateWrapper.set("name", entity.getName());
        }
        if (null != entity.getShortName()) {
            updateWrapper.set("short_name", entity.getShortName());
        }
        if (null != entity.getSort()) {
            updateWrapper.set("sort", entity.getSort());
        }
        if (null != entity.getDeleted()) {
            updateWrapper.set("deleted", entity.getDeleted());
        }
        if (null != entity.getLevel()) {
            updateWrapper.set("level", entity.getLevel());
        }
        if (null != entity.getLatitude()) {
            updateWrapper.set("latitude", entity.getLatitude());
        }
        if (null != entity.getLongitude()) {
            updateWrapper.set("longitude", entity.getLongitude());
        }
        if (null != entity.getParentId()) {
            updateWrapper.set("parent_id", entity.getParentId());
        }
        return updateWrapper;
    }

    @Override
    public void revert() {
        List<Map<String, Object>> maps = baseMapper.selectToMaps();
        List<AdministrativeDivisionDO> list = new ArrayList<>();
        Date date = new Date();
        maps.forEach(item -> {
            AdministrativeDivisionDO administrativeDivisionDO = new AdministrativeDivisionDO();
            administrativeDivisionDO.setIid(MapUtils.getLongValue(item, "ID"));
            administrativeDivisionDO.setGmtCreate(date);
            administrativeDivisionDO.setGmtModify(date);
            administrativeDivisionDO.setDeleted("0");
            administrativeDivisionDO.setVersion(1);
            administrativeDivisionDO.setCode("");
            administrativeDivisionDO.setName(MapUtils.getString(item, "NAME"));
            administrativeDivisionDO.setShortName(MapUtils.getString(item, "SHORT_NAME"));
            administrativeDivisionDO.setParentId(MapUtils.getLongValue(item, "PARENT_ID"));
            administrativeDivisionDO.setLevel(MapUtils.getIntValue(item, "LEVEL"));
            administrativeDivisionDO.setLongitude(new BigDecimal(MapUtils.getFloatValue(item,"LONGITUDE")));
            administrativeDivisionDO.setLatitude(new BigDecimal(MapUtils.getFloatValue(item,"LATITUDE")));
            administrativeDivisionDO.setSort(MapUtils.getIntValue(item, "SORT"));
            administrativeDivisionDO.setLongitudeUnit("E");
            administrativeDivisionDO.setLatitudeUnit("N");
            list.add(administrativeDivisionDO);
        });
        insertBatch(list);
    }

}

